﻿using System;
using System.Collections.Generic;
//using System.Linq;
//using System.Text;
using Allegro.Framework;

namespace Allegro.Integrator
{
    /// <summary>
    /// Compute the first order derivatives of the variables
    /// </summary>
    /// <param name="x"></param>
    /// <param name="yIn">Input y values</param>
    /// <param name="dydx">dydx[i] is the derivative dy[i]/dx</param>
    /// <param name="completed">completed[i] is true if dydx[i] was computed</param>
    /// <returns>True if all variables were computed, false otherwise</returns>
    public delegate bool Derivative(double x, double[] yIn, ref double[] dydx, ref bool[] completed);

    /// <summary>
    /// ComputeValues may compute both absolute y values and derivatives. 
    /// method indicates which output vector should be used for each variable.
    /// If method[i]==ComputationMethod.DirectComputation, then an absolute y value was computed
    /// for variable i, and the value is yOut[i]. 
    /// If method[i]==Derivative, then a derivative dy/dx was computed for variable i, and the value is
    /// dydx[i].
    /// </summary>
    /// <param name="x">x value</param>
    /// <param name="yIn">Input y values</param>
    /// <param name="yOut">Computed y values (if method[i]==DirectComputation)</param>
    /// <param name="dydx">Computed dy/dx values (if method[i]==Derivative)</param>
    /// <param name="integrated">integrated[i] is true if variable i has already been integrated</param>
    /// <param name="completed">completed[i] is true if yOut[i] was computed</param>
    /// <returns>True if all variables were completed, false otherwise</returns>
    public delegate bool ComputeValues(double x, double[] yIn, ref double[] yOut, bool[] integrated, ref bool[] completed);

    /// <summary>
    /// ODE Integrator interfacce
    /// </summary>
    public interface IODEIntegrator
    {
        /// <summary>
        /// Relative accuracy
        /// </summary>
        double Accuracy
        {
            get;
            set;
        }
        /// <summary>
        /// Integration step. Input are the dependent variable vector y[1..n] and its derivative dydx[1..n]
        /// at the starting value of the independent varable x. Also input are the stepsize to be attempted, 
        /// htry, and the vector yscal[1..n], against which the error is scaled. On output, y and x are replaced by their
        /// new values, hdid is the stepsize that was actually accomplished, and hnext is the estimated next stepsize. 
        /// derivs is the user-supplied method that computes the right-hand side derivatives. switches is a boolean
        /// array that switches individual equations on or off. If switches[i] == true, then equation i will be integrated
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="dydx"></param>
        /// <param name="yscal"></param>
        /// <param name="htry"></param>
        /// <param name="hdid"></param>
        /// <param name="hnext"></param>
        /// <param name="f"></param>
        /// <param name="switches"></param>
        //void Integrate(ref double x, ref double[] y, double[] dydx, double[] yscal, double htry, out double hdid, out double hnext, Derivative f, ComputeValues V);
        void Integrate(ref double x, ref double[] y, double htry, out double hdid, out double hnext, Derivative f, ComputeValues V);

        /// <summary>
        /// Integration switch
        /// </summary>
        //ISwitch Switch { get; }

        /// <summary>
        /// Set equation switch for equation i
        /// </summary>
        /// <param name="i"></param>
        /// <param name="switchValue"></param>
        //void SetSwitch(int i, bool switchValue);

        /// <summary>
        /// Get equation switch for equation i
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        //bool GetSwitch(int i);
    }

    //public interface ISwitch
    //{
    //    /// <summary>
    //    /// Get/set switch for equation# i
    //    /// </summary>
    //    /// <param name="i"></param>
    //    /// <returns></returns>
    //    bool this[int i]{get;set;}
    //}
}
